"""
类型管理服务
提供统一的类型数据管理，支持缓存、版本控制和实时更新
"""
from datetime import datetime, timedelta, timezone
import asyncio
import hashlib
import json
from typing import Any
from motor.motor_asyncio import AsyncIOMotorDatabase
from ..core.response import ErrorTypes


class TypeService:
    """类型管理服务"""
    
    def __init__(self):
        self._version_cache: dict[str, str] = {}
        self._etag_cache: dict[str, str] = {}
        self._last_modified: dict[str, datetime] = {}
        self._lock: asyncio.Lock = asyncio.Lock()
    
    async def get_type_options(
        self, 
        db: AsyncIOMotorDatabase,
        module_type: str,
        force_refresh: bool = False,
        if_none_match: str | None = None,
        if_modified_since: datetime | None = None
    ) -> tuple[list[dict[str, str | int | bool | None]], str, datetime]:
        """
        获取类型选项
        
        Args:
            db: 数据库连接
            module_type: 模块类型
            force_refresh: 是否强制刷新缓存
            if_none_match: ETag验证
            if_modified_since: 最后修改时间验证
            
        Returns:
            (类型选项列表, ETag, 最后修改时间)
        """
        cache_key = f"type_options_{module_type}"
        
        async with self._lock:
            # 检查ETag和最后修改时间
            current_etag = self._etag_cache.get(cache_key)
            current_last_modified = self._last_modified.get(cache_key)
            
            if if_none_match and current_etag and if_none_match == current_etag:
                raise TypeNotModifiedError("类型数据未修改")
            
            if (if_modified_since and current_last_modified and 
                if_modified_since >= current_last_modified):
                raise TypeNotModifiedError("类型数据未修改")
            
            if not force_refresh and self._is_cache_valid(cache_key):
                cached_options = self._get_cached_options(cache_key)
                if cached_options and current_etag is not None and current_last_modified is not None:
                    return cached_options, current_etag, current_last_modified
            
            # 从数据库获取数据
            try:
                cursor = db.types.find({"module_type": module_type, "is_enabled": True}).sort("sort_order", 1)
                types = await cursor.to_list(length=None)
                
                options = [
                    {
                        "label": t["name"],
                        "value": t["code"],
                        "color": t.get("color", "#1890ff"),
                        "disabled": not t.get("is_enabled", True)
                    } for t in types
                ]
                
                new_etag = self._generate_etag(options)
                new_last_modified = datetime.now(timezone.utc)
                
                self._update_cache(cache_key, options, new_etag, new_last_modified)
                
                return options, new_etag, new_last_modified
                
            except Exception as e:
                cached_options = self._get_cached_options(cache_key)
                if cached_options and current_etag is not None and current_last_modified is not None:
                    return cached_options, current_etag, current_last_modified
                raise TypeServiceError(f"获取类型选项失败: {str(e)}")
    
    async def get_all_type_options(
        self, 
        db: AsyncIOMotorDatabase,
        force_refresh: bool = False
    ) -> dict[str, list[dict[str, str | int | bool | None]]]:
        """获取所有模块的类型选项"""
        result = {}
        
        # 从数据库动态获取所有模块类型
        try:
            module_types = await db.types.distinct("module_type")
        except Exception as e:
            raise TypeServiceError(f"获取模块类型失败: {str(e)}")
        
        for module_type in module_types:
            try:
                options, _, _ = await self.get_type_options(
                    db, module_type, force_refresh
                )
                result[module_type] = options
            except Exception as e:
                print(f"获取{module_type}类型选项失败: {str(e)}")
                result[module_type] = []
        
        return result
    
    async def refresh_cache(self, module_type: str | None = None) -> dict[str, int | list[str]]:
        """
        刷新缓存
        
        Args:
            module_type: 模块类型，如果为None则刷新所有模块
            
        Returns:
            包含刷新结果的字典
        """
        try:
            refreshed_modules: list[str] = []
            
            if module_type:
                # 清除指定模块的缓存
                cache_key = f"type_options_{module_type}"
                
                if cache_key in self._etag_cache or cache_key in self._last_modified or cache_key in self._version_cache:
                    _ = self._etag_cache.pop(cache_key, None)
                    _ = self._last_modified.pop(cache_key, None)
                    _ = self._version_cache.pop(cache_key, None)
                    refreshed_modules.append(module_type)
            else:
                # 清除所有缓存
                for cache_key in list(self._etag_cache.keys()):
                    if cache_key.startswith("type_options_"):
                        module = cache_key.replace("type_options_", "")
                        if module:
                            refreshed_modules.append(module)
                
                self._etag_cache.clear()
                self._last_modified.clear()
                self._version_cache.clear()
            
            return {
                "refreshed_modules": refreshed_modules,
                "refreshed_count": len(refreshed_modules)
            }
                
        except Exception as e:
            raise TypeServiceError(f"刷新缓存失败: {str(e)}")
    
    def _is_cache_valid(self, cache_key: str) -> bool:
        """检查缓存是否有效"""
        return (
            cache_key in self._etag_cache and 
            cache_key in self._last_modified and 
            cache_key in self._version_cache and
            (datetime.now(timezone.utc) - self._last_modified[cache_key]) < timedelta(minutes=15)
        )
    
    def _get_cached_options(self, cache_key: str) -> list[dict[str, str | int | bool | None]] | None:
        """获取缓存的选项"""
        if cache_key in self._version_cache:
            return self._version_cache.get(cache_key, [])
    
    def _generate_etag(self, data: list[dict[str, str | int | bool | None]]) -> str:
        """生成ETag"""
        data_str = json.dumps(data, sort_keys=True)
        return hashlib.md5(data_str.encode()).hexdigest()
    
    def _update_cache(
        self, 
        cache_key: str, 
        data: list[dict[str, Any]], 
        etag: str, 
        last_modified: datetime
    ):
        """更新缓存"""
        self._etag_cache[cache_key] = etag
        self._last_modified[cache_key] = last_modified
        self._version_cache[cache_key] = data
    
    async def initialize_default_types(self, db: AsyncIOMotorDatabase, module_type: str) -> int:
        """初始化指定模块的默认类型"""
        from ..models.type import ModuleType

        type_definitions = {
            ModuleType.REQUIREMENT: [
                {"name": "功能性需求", "code": "functional", "color": "#409EFF", "sort_order": 1},
                {"name": "非功能性需求", "code": "non_functional", "color": "#67C23A", "sort_order": 2},
                {"name": "业务需求", "code": "business", "color": "#E6A23C", "sort_order": 3},
                {"name": "技术需求", "code": "technical", "color": "#F56C6C", "sort_order": 4},
                {"name": "接口需求", "code": "interface", "color": "#909399", "sort_order": 5},
                {"name": "性能需求", "code": "performance", "color": "#606266", "sort_order": 6},
                {"name": "安全需求", "code": "security", "color": "#F56C6C", "sort_order": 7},
                {"name": "可用性需求", "code": "usability", "color": "#67C23A", "sort_order": 8}
            ]
        }

        # 将字符串转换为枚举值进行比较
        module_type_enum = None
        for mt in ModuleType:
            if mt.value == module_type:
                module_type_enum = mt
                break
        
        if module_type_enum is None or module_type_enum not in type_definitions:
            raise TypeServiceError(f"无效的模块类型: {module_type}")

        types_to_create = type_definitions[module_type_enum]
        created_count = 0

        for type_item in types_to_create:
            type_doc = {
                "module_type": module_type,
                "name": type_item["name"],
                "code": type_item["code"],
                "color": type_item.get("color", "#1890ff"),
                "sort_order": type_item["sort_order"],
                "is_enabled": True,
                "created_at": datetime.now(timezone.utc),
                "updated_at": datetime.now(timezone.utc)
            }
            
            await db.types.update_one(
                {"module_type": module_type, "code": type_item["code"]},
                {"$set": type_doc},
                upsert=True
            )
            created_count += 1
        
        await self.refresh_cache(module_type)
        return created_count


class TypeServiceError(Exception):
    """类型服务错误"""
    
    def __init__(self, message: str, error_type: str = ErrorTypes.INTERNAL_ERROR):
        self.message: str = message
        self.error_type: str = error_type
        super().__init__(message)


class TypeNotModifiedError(TypeServiceError):
    """类型数据未修改错误"""
    def __init__(self, message: str = "类型数据未修改"):
        super().__init__(message, ErrorTypes.NOT_MODIFIED_ERROR)


# 全局类型服务实例
type_service = TypeService()


